"""
物流管理相关的API
包括物流服务商、物流单和跟踪节点相关的功能
"""
from flask import request, jsonify, current_app
from flask_jwt_extended import jwt_required, current_user
from sqlalchemy.exc import SQLAlchemyError
from marshmallow import ValidationError
from datetime import datetime

from app.extensions import db
from app.models.logistics import LogisticsProvider, Logistics, TrackingNode, LogisticsStatus
from app.models.order import Order, OrderStatus
from app.schemas.logistics import LogisticsProviderSchema, LogisticsSchema, TrackingNodeSchema, LogisticsUpdateSchema, TrackingNodeCreateSchema
from app.utils.errors import NotFoundError, BadRequestError, ForbiddenError
from app.api.v1 import api_v1

# ===== 物流服务商 =====

@api_v1.route('/logistics/providers', methods=['GET'])
def get_logistics_providers():
    """获取物流服务商列表"""
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 20, type=int)
    is_active = request.args.get('is_active')
    
    # 构建查询
    query = LogisticsProvider.query
    
    if is_active is not None:
        is_active = is_active.lower() == 'true'
        query = query.filter_by(is_active=is_active)
    
    # 分页
    pagination = query.order_by(LogisticsProvider.name).paginate(page=page, per_page=per_page)
    
    return jsonify({
        "total": pagination.total,
        "pages": pagination.pages,
        "page": page,
        "per_page": per_page,
        "providers": [provider.to_dict() for provider in pagination.items]
    }), 200

@api_v1.route('/logistics/providers/<int:provider_id>', methods=['GET'])
def get_logistics_provider(provider_id):
    """获取物流服务商详情"""
    provider = LogisticsProvider.query.get_or_404(provider_id)
    
    return jsonify(provider.to_dict()), 200

@api_v1.route('/logistics/providers', methods=['POST'])
@jwt_required()
def create_logistics_provider():
    """创建物流服务商"""
    # 非管理员不能创建物流服务商
    if not current_user.is_admin:
        raise ForbiddenError("权限不足，只有管理员可以创建物流服务商")
    
    data = request.get_json()
    
    if not data:
        raise BadRequestError("请求参数为空")
    
    # 验证数据
    schema = LogisticsProviderSchema()
    try:
        # 使用schema验证数据
        validated_data = schema.load(data)
    except ValidationError as e:
        return jsonify({"msg": "数据验证错误", "errors": e.messages}), 400
    
    # 创建物流服务商
    provider = LogisticsProvider(
        name=data['name'],
        description=data.get('description'),
        website=data.get('website'),
        contact=data.get('contact'),
        is_active=data.get('is_active', True)
    )
    
    try:
        db.session.add(provider)
        db.session.commit()
    except SQLAlchemyError as e:
        db.session.rollback()
        current_app.logger.error(f"创建物流服务商失败: {str(e)}")
        return jsonify({"msg": "创建物流服务商失败", "error": str(e)}), 500
    
    return jsonify({
        "msg": "物流服务商创建成功",
        "provider": provider.to_dict()
    }), 201

@api_v1.route('/logistics/providers/<int:provider_id>', methods=['PUT'])
@jwt_required()
def update_logistics_provider(provider_id):
    """更新物流服务商"""
    # 非管理员不能更新物流服务商
    if not current_user.is_admin:
        raise ForbiddenError("权限不足，只有管理员可以更新物流服务商")
    
    provider = LogisticsProvider.query.get_or_404(provider_id)
    data = request.get_json()
    
    if not data:
        raise BadRequestError("请求参数为空")
    
    # 验证数据
    schema = LogisticsProviderSchema()
    try:
        # 使用schema验证数据
        validated_data = schema.load(data)
    except ValidationError as e:
        return jsonify({"msg": "数据验证错误", "errors": e.messages}), 400
    
    # 更新字段
    if 'name' in data:
        provider.name = data['name']
    if 'description' in data:
        provider.description = data['description']
    if 'website' in data:
        provider.website = data['website']
    if 'contact' in data:
        provider.contact = data['contact']
    if 'is_active' in data:
        provider.is_active = data['is_active']
    
    try:
        db.session.commit()
    except SQLAlchemyError as e:
        db.session.rollback()
        current_app.logger.error(f"更新物流服务商失败: {str(e)}")
        return jsonify({"msg": "更新物流服务商失败", "error": str(e)}), 500
    
    return jsonify({
        "msg": "物流服务商更新成功",
        "provider": provider.to_dict()
    }), 200

# ===== 物流单 =====

@api_v1.route('/logistics', methods=['GET'])
@jwt_required()
def get_logistics():
    """获取物流单列表"""
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 20, type=int)
    status = request.args.get('status')
    provider_id = request.args.get('provider_id', type=int)
    tracking_number = request.args.get('tracking_number')
    order_id = request.args.get('order_id', type=int)
    
    # 构建查询
    query = Logistics.query
    
    # 非管理员只能查看与自己订单相关的物流单
    if not current_user.is_admin:
        # 获取当前用户的所有订单ID
        user_order_ids = [order.id for order in Order.query.filter_by(user_id=current_user.id)]
        query = query.filter(Logistics.order_id.in_(user_order_ids))
    
    if status:
        query = query.filter_by(status=status)
    
    if provider_id:
        query = query.filter_by(provider_id=provider_id)
    
    if tracking_number:
        query = query.filter_by(tracking_number=tracking_number)
    
    if order_id:
        query = query.filter_by(order_id=order_id)
    
    # 分页
    pagination = query.order_by(Logistics.created_at.desc()).paginate(page=page, per_page=per_page)
    
    return jsonify({
        "total": pagination.total,
        "pages": pagination.pages,
        "page": page,
        "per_page": per_page,
        "logistics": [logistics.to_dict() for logistics in pagination.items]
    }), 200

@api_v1.route('/logistics/<int:logistics_id>', methods=['GET'])
@jwt_required()
def get_logistics_detail(logistics_id):
    """获取物流单详情"""
    logistics = Logistics.query.get_or_404(logistics_id)
    
    # 非管理员只能查看与自己订单相关的物流单
    if not current_user.is_admin:
        order = Order.query.get(logistics.order_id)
        if order.user_id != current_user.id:
            raise ForbiddenError("权限不足，无法查看其他用户的物流单")
    
    return jsonify(logistics.to_dict(include_nodes=True)), 200

@api_v1.route('/logistics', methods=['POST'])
@jwt_required()
def create_logistics():
    """创建物流单"""
    # 非管理员不能创建物流单
    if not current_user.is_admin:
        raise ForbiddenError("权限不足，只有管理员可以创建物流单")
    
    data = request.get_json()
    
    if not data:
        raise BadRequestError("请求参数为空")
    
    # 验证数据
    schema = LogisticsSchema()
    try:
        # 使用schema验证数据
        validated_data = schema.load(data)
    except ValidationError as e:
        return jsonify({"msg": "数据验证错误", "errors": e.messages}), 400
    
    # 获取关联的订单
    order = Order.query.get(data['order_id'])
    if not order:
        return jsonify({"msg": "订单不存在"}), 400
    
    # 检查订单状态
    if order.status not in [OrderStatus.PROCESSING.value]:
        return jsonify({"msg": "订单状态不允许创建物流单"}), 400
    
    # 创建物流单
    logistics = Logistics(
        order_id=data['order_id'],
        provider_id=data['provider_id'],
        tracking_number=data['tracking_number'],
        status=LogisticsStatus.PENDING.value,
        shipping_address=data['shipping_address'],
        shipping_date=data.get('shipping_date')
    )
    
    # 创建初始跟踪节点
    tracking_node = TrackingNode(
        logistics=logistics,
        status=LogisticsStatus.PENDING.value,
        location="处理中心",
        description="物流单已创建，等待处理"
    )
    
    # 更新订单状态
    order.status = OrderStatus.SHIPPED.value
    
    try:
        db.session.add(logistics)
        db.session.add(tracking_node)
        db.session.commit()
    except SQLAlchemyError as e:
        db.session.rollback()
        current_app.logger.error(f"创建物流单失败: {str(e)}")
        return jsonify({"msg": "创建物流单失败", "error": str(e)}), 500
    
    return jsonify({
        "msg": "物流单创建成功",
        "logistics": logistics.to_dict(include_nodes=True)
    }), 201

@api_v1.route('/logistics/<int:logistics_id>', methods=['PUT'])
@jwt_required()
def update_logistics(logistics_id):
    """更新物流单"""
    # 非管理员不能更新物流单
    if not current_user.is_admin:
        raise ForbiddenError("权限不足，只有管理员可以更新物流单")
    
    logistics = Logistics.query.get_or_404(logistics_id)
    data = request.get_json()
    
    if not data:
        raise BadRequestError("请求参数为空")
    
    # 验证数据
    schema = LogisticsUpdateSchema()
    try:
        # 使用schema验证数据
        validated_data = schema.load(data)
    except ValidationError as e:
        return jsonify({"msg": "数据验证错误", "errors": e.messages}), 400
    
    # 更新字段
    if 'status' in data:
        logistics.status = data['status']
        
        # 如果设置为已送达，自动设置送达日期
        if data['status'] == LogisticsStatus.DELIVERED.value and not logistics.delivery_date:
            logistics.delivery_date = datetime.utcnow()
            
            # 更新订单状态
            order = Order.query.get(logistics.order_id)
            if order:
                order.status = OrderStatus.DELIVERED.value
    
    if 'shipping_date' in data:
        logistics.shipping_date = data['shipping_date']
    
    if 'delivery_date' in data:
        logistics.delivery_date = data['delivery_date']
    
    try:
        db.session.commit()
    except SQLAlchemyError as e:
        db.session.rollback()
        current_app.logger.error(f"更新物流单失败: {str(e)}")
        return jsonify({"msg": "更新物流单失败", "error": str(e)}), 500
    
    return jsonify({
        "msg": "物流单更新成功",
        "logistics": logistics.to_dict()
    }), 200

# ===== 跟踪节点 =====

@api_v1.route('/logistics/<int:logistics_id>/tracking-nodes', methods=['GET'])
@jwt_required()
def get_tracking_nodes(logistics_id):
    """获取物流单的跟踪节点列表"""
    logistics = Logistics.query.get_or_404(logistics_id)
    
    # 非管理员只能查看与自己订单相关的物流单的跟踪节点
    if not current_user.is_admin:
        order = Order.query.get(logistics.order_id)
        if order.user_id != current_user.id:
            raise ForbiddenError("权限不足，无法查看其他用户的物流单跟踪节点")
    
    # 按时间倒序排列
    nodes = TrackingNode.query.filter_by(logistics_id=logistics_id).order_by(TrackingNode.timestamp.desc()).all()
    
    return jsonify({
        "logistics_id": logistics_id,
        "tracking_number": logistics.tracking_number,
        "nodes": [node.to_dict() for node in nodes]
    }), 200

@api_v1.route('/logistics/<int:logistics_id>/tracking-nodes', methods=['POST'])
@jwt_required()
def add_tracking_node(logistics_id):
    """添加物流单跟踪节点"""
    # 非管理员不能添加跟踪节点
    if not current_user.is_admin:
        raise ForbiddenError("权限不足，只有管理员可以添加跟踪节点")
    
    logistics = Logistics.query.get_or_404(logistics_id)
    data = request.get_json()
    
    if not data:
        raise BadRequestError("请求参数为空")
    
    # 添加物流单ID到数据中
    data['logistics_id'] = logistics_id
    
    # 验证数据
    schema = TrackingNodeCreateSchema()
    try:
        # 使用schema验证数据
        validated_data = schema.load(data)
    except ValidationError as e:
        return jsonify({"msg": "数据验证错误", "errors": e.messages}), 400
    
    # 创建跟踪节点
    node = TrackingNode(
        logistics_id=logistics_id,
        status=data['status'],
        location=data.get('location'),
        description=data.get('description')
    )
    
    # 更新物流单状态
    logistics.status = data['status']
    
    # 如果是已送达状态，设置送达日期
    if data['status'] == LogisticsStatus.DELIVERED.value and not logistics.delivery_date:
        logistics.delivery_date = datetime.utcnow()
        
        # 更新订单状态
        order = Order.query.get(logistics.order_id)
        if order:
            order.status = OrderStatus.DELIVERED.value
    
    try:
        db.session.add(node)
        db.session.commit()
    except SQLAlchemyError as e:
        db.session.rollback()
        current_app.logger.error(f"添加跟踪节点失败: {str(e)}")
        return jsonify({"msg": "添加跟踪节点失败", "error": str(e)}), 500
    
    return jsonify({
        "msg": "跟踪节点添加成功",
        "node": node.to_dict()
    }), 201 